Dynamics AX has a very useful feature, which allows
saving the latest user choices per user per form. This feature is
implemented across a number of standard reports, periodic jobs, and
other objects, which require user input.
When developing a
new functionality for Dynamics AX, I always try to keep that practice.
One of the frequently used areas is custom filters for grid-based forms.
Although, Dynamics AX allows users to use standard filtering for any
grid, in practice sometimes it is not very useful, especially when the
user requires something specific.
In this recipe, we will see
how to store the latest user filter selections. To make it as simple as
possible, we will use existing filters on the General journal form, which can be opened from General ledger | Journals | General journal. This form contains two filters— Show and Show user-created only. Show allows displaying journals by their posting status and Show user-created only toggles between all journals and the currently logged user's journals.
How to do it...
1. Find the LedgerJournalTable form in AOT, and add the following code to the bottom of its class declaration:
AllOpenPosted showStatus;
NoYes showCurrentUser;
#define.CurrentVersion(1)
#localmacro.CurrentList
showStatus,
showCurrentUser
#endmacro
2. Create these additional form methods:
public void initParmDefault()
{;
showStatus = AllOpenPosted::Open;
showCurrentUser = true;
}
public container pack()
{
return [#CurrentVersion,#CurrentList];
}
public boolean unpack(container packedClass)
{
int version = RunBase::getVersion(packedClass);
;
last form valueslast form valuesstoringswitch (version)
{
case #CurrentVersion:
[version,#CurrentList] = packedClass;
return true;
default:
return false;
}
return false;
}
public identifiername lastValueDesignName()
{
return element.args().menuItemName();
}
public identifiername lastValueElementName()
{
return this.name();
}
public UtilElementType lastValueType()
{
return UtilElementType::Form;
}
public userId lastValueUserId()
{
return curuserid();
}
public dataAreaId lastValueDataAreaId()
{
return curext();
}
3. Add the following code to the bottom of the form's run():
xSysLastValue::getLast(this);
AllOpenPostedField.selection(showStatus);
ShowUserCreatedOnly.value(showCurrentUser);
journalFormTable.designSelectionChangeAllOpenPosted();
journalFormTable.designSelectionChangeShowUserCreateOnly();
4. And the following code to the bottom of the form's close():
showStatus = AllOpenPostedField.selection();
showCurrentUser = ShowUserCreatedOnly.value();
xSysLastValue::saveLast(this);
5. Now to test the form, open General ledger | Journals | General journal, change filter values, close it, and run again. The latest filter selections should stay:
How it works...
First of all, we define some variables. We will store the journal posting status filter value in showStatus and the current user filter value in showCurrentUser.
The macro #CurrentList is used to define a list of variables that we are going to store. Currently, we have two variables.
The macro #CurrentVersion defines a version of saved values. In other words, it says that the variables defined by the #CurrentList, which will be stored in system cache later, can be addressed using the number 1.
Normally, when implementing last value saving for the first time for particular object, #CurrentVersion is set to 1. Later on, if we decide to add new values or change existing ones, we have to change the value of #CurrentVersion,
normally increasing it by 1. This ensures that the system addresses the
correct list of variables in the cache and does not break existing
functionality.
The initParmDefault()method specifies
default values if nothing is found in the system cache. Normally, this
happens if we run a form for the first time, we change #CurrentVersion or clean the cache. Later, this method is called automatically by the xSysLastValue object.
The methods pack() and unpack()
are responsible for formatting a storage container from variables and
extracting variables from a storage container respectively. In our case, pack()
returns a container consisting of three values: version number, posting
status, and current user toggle. Those values will be sent to the
system cache after the form is closed. During an opening of the form,
the xSysLastValue object uses unpack()
to extract values from the stored container. It checks the container
version from cache first, and if it matches the current version number,
then the values from the cache are considered correct and are assigned
to the form variables.
A combination of lastValueDesignName(), lastValueElementName(), lastValueType(), lastValueUserId(), and lastValueDataAreaId()
return values form unique string representing saved values. This
ensures that different users can store last values for different objects
without overriding each other's values in cache.
The lastValueDesignName()
method is meant to return the name of the object's current design in
cases where the object can have several designs. In this recipe, there
is only one design, so instead of leaving it empty, I used it for a
slightly different purpose. The same LedgerJournalTable AOT form can represent different user forms like Ledger journal, Periodic journal, Vendor payment journal,
and so on depending on the location from which it was opened. To ensure
that the user's latest choices are saved correctly, we included the
opening menu item name as part of the unique string.
The last two pieces of code need to be added to the bottom of the form's run() and close(). In the run() method, xSysLastValue::getLast(this)
retrieves saved user values from cache and assigns them to the form's
variables. The next two lines assign the same values to the respective
form controls. designSelectionChangeAllOpenPosted() and designSelectionChangeShowUserCreateOnly()
execute a form query to apply updated filters. Although both of those
methods currently perform exactly the same action, we keep both for the
future in case this functionality is updated. Code lines in close() are responsible for assigning user selections to variables and saving them to cache by calling xSysLastValue::saveLast(this).